//! # 错误处理策略测试模块

use super::*;
use crate::{InMemoryDeadLetterQueue, DeadLetterConfig, ExponentialBackoffStrategy};
use std::sync::Arc;
use std::time::Duration;

#[tokio::test]
async fn test_retry_error_handler() {
    let retry_strategy = Arc::new(ExponentialBackoffStrategy::new(
        Duration::from_millis(100),
        Duration::from_secs(30),
        2.0
    ).with_max_attempts(3));
    
    let handler = RetryErrorHandler::new(retry_strategy);
    let context = ErrorContext {
        component: "test-component".to_string(),
        retry_count: 1,
        message_id: Some("msg-123".to_string()),
        topic: Some("test.topic".to_string()),
        attributes: std::collections::HashMap::new(),
    };
    
    let error = crate::ResilienceError::internal_error("test error");
    let result = handler.handle_error(&error, &context).await.unwrap();
    
    match result {
        ErrorHandlingResult::Retry { delay } => {
            assert!(delay >= Duration::from_millis(90));
            assert!(delay <= Duration::from_millis(110));
        }
        _ => panic!("Expected retry result"),
    }
}

#[tokio::test]
async fn test_retry_handler_max_attempts() {
    let retry_strategy = Arc::new(ExponentialBackoffStrategy::new(
        Duration::from_millis(100),
        Duration::from_secs(30),
        2.0
    ).with_max_attempts(2));
    
    let handler = RetryErrorHandler::new(retry_strategy);
    let context = ErrorContext {
        component: "test-component".to_string(),
        retry_count: 2, // 超过最大重试次数
        message_id: Some("msg-123".to_string()),
        topic: Some("test.topic".to_string()),
        attributes: std::collections::HashMap::new(),
    };
    
    let error = crate::ResilienceError::internal_error("test error");
    let result = handler.handle_error(&error, &context).await.unwrap();
    
    match result {
        ErrorHandlingResult::SendToDeadLetter => {
            // 预期结果
        }
        _ => panic!("Expected dead letter result"),
    }
}

#[tokio::test]
async fn test_dead_letter_error_handler() {
    let config = DeadLetterConfig::default();
    let dlq = Arc::new(InMemoryDeadLetterQueue::new(config));
    let handler = DeadLetterErrorHandler::new(dlq);
    
    let context = ErrorContext::default();
    let error = crate::ResilienceError::internal_error("test error");
    
    let result = handler.handle_error(&error, &context).await.unwrap();
    
    match result {
        ErrorHandlingResult::SendToDeadLetter => {
            // 预期结果
        }
        _ => panic!("Expected dead letter result"),
    }
}

#[tokio::test]
async fn test_skip_error_handler() {
    let handler = SkipErrorHandler::new();
    let context = ErrorContext::default();
    let error = crate::ResilienceError::internal_error("test error");
    
    let result = handler.handle_error(&error, &context).await.unwrap();
    
    match result {
        ErrorHandlingResult::Skip => {
            // 预期结果
        }
        _ => panic!("Expected skip result"),
    }
}

#[tokio::test]
async fn test_composite_error_handler() {
    let retry_strategy = Arc::new(ExponentialBackoffStrategy::new(
        Duration::from_millis(100),
        Duration::from_secs(30),
        2.0
    ).with_max_attempts(3));
    
    let retry_handler = Arc::new(RetryErrorHandler::new(retry_strategy));
    let skip_handler = Arc::new(SkipErrorHandler::new());
    
    let composite_handler = CompositeErrorHandler::new()
        .add_handler(retry_handler)
        .add_handler(skip_handler);
    
    let context = ErrorContext {
        component: "test-component".to_string(),
        retry_count: 1,
        message_id: Some("msg-123".to_string()),
        topic: Some("test.topic".to_string()),
        attributes: std::collections::HashMap::new(),
    };
    
    let error = crate::ResilienceError::internal_error("test error");
    let result = composite_handler.handle_error(&error, &context).await.unwrap();
    
    // 第一个处理器（重试处理器）应该处理这个错误
    match result {
        ErrorHandlingResult::Retry { .. } => {
            // 预期结果
        }
        _ => panic!("Expected retry result from composite handler"),
    }
}

#[test]
fn test_error_classification() {
    let classifier = DefaultErrorClassifier;
    
    // 测试临时性错误
    let timeout_error = crate::ResilienceError::timeout_error("connection timeout");
    assert!(matches!(
        classifier.classify(&timeout_error),
        ErrorClassification::Transient
    ));
    
    // 测试永久性错误
    let perm_error = crate::ResilienceError::config_error("permission denied");
    assert!(matches!(
        classifier.classify(&perm_error),
        ErrorClassification::Permanent
    ));
    
    // 测试系统错误
    let sys_error = crate::ResilienceError::internal_error("system failure");
    assert!(matches!(
        classifier.classify(&sys_error),
        ErrorClassification::System
    ));
    
    // 测试业务错误
    let biz_error = crate::ResilienceError::config_error("validation failed");
    assert!(matches!(
        classifier.classify(&biz_error),
        ErrorClassification::Business
    ));
    
    // 测试未知错误
    let unknown_error = crate::ResilienceError::internal_error("unknown issue");
    assert!(matches!(
        classifier.classify(&unknown_error),
        ErrorClassification::Unknown
    ));
}

#[tokio::test]
async fn test_smart_error_handler_transient_error() {
    let retry_strategy = Arc::new(ExponentialBackoffStrategy::new(
        Duration::from_millis(100),
        Duration::from_secs(30),
        2.0
    ).with_max_attempts(3));
    
    let config = DeadLetterConfig::default();
    let dlq = Arc::new(InMemoryDeadLetterQueue::new(config));
    
    let retry_handler = Arc::new(RetryErrorHandler::new(retry_strategy));
    let dead_letter_handler = Arc::new(DeadLetterErrorHandler::new(dlq));
    
    let smart_handler = SmartErrorHandler::new(retry_handler, dead_letter_handler);
    
    let context = ErrorContext {
        component: "test-component".to_string(),
        retry_count: 1,
        message_id: Some("msg-123".to_string()),
        topic: Some("test.topic".to_string()),
        attributes: std::collections::HashMap::new(),
    };
    
    // 临时性错误（超时）
    let error = crate::ResilienceError::timeout_error("connection timeout");
    let result = smart_handler.handle_error(&error, &context).await.unwrap();
    
    match result {
        ErrorHandlingResult::Retry { .. } => {
            // 临时性错误应该重试
        }
        _ => panic!("Expected retry for transient error"),
    }
}

#[tokio::test]
async fn test_smart_error_handler_permanent_error() {
    let retry_strategy = Arc::new(ExponentialBackoffStrategy::new(
        Duration::from_millis(100),
        Duration::from_secs(30),
        2.0
    ).with_max_attempts(3));
    
    let config = DeadLetterConfig::default();
    let dlq = Arc::new(InMemoryDeadLetterQueue::new(config));
    
    let retry_handler = Arc::new(RetryErrorHandler::new(retry_strategy));
    let dead_letter_handler = Arc::new(DeadLetterErrorHandler::new(dlq));
    
    let smart_handler = SmartErrorHandler::new(retry_handler, dead_letter_handler);
    
    let context = ErrorContext::default();
    
    // 永久性错误（权限）
    let error = crate::ResilienceError::config_error("permission denied");
    let result = smart_handler.handle_error(&error, &context).await.unwrap();
    
    match result {
        ErrorHandlingResult::SendToDeadLetter => {
            // 永久性错误应该直接发送到死信队列
        }
        _ => panic!("Expected dead letter for permanent error"),
    }
}

#[tokio::test]
async fn test_smart_error_handler_business_error() {
    let retry_strategy = Arc::new(ExponentialBackoffStrategy::new(
        Duration::from_millis(100),
        Duration::from_secs(30),
        2.0
    ).with_max_attempts(3));
    
    let config = DeadLetterConfig::default();
    let dlq = Arc::new(InMemoryDeadLetterQueue::new(config));
    
    let retry_handler = Arc::new(RetryErrorHandler::new(retry_strategy));
    let dead_letter_handler = Arc::new(DeadLetterErrorHandler::new(dlq));
    
    let smart_handler = SmartErrorHandler::new(retry_handler, dead_letter_handler);
    
    let context = ErrorContext::default();
    
    // 业务错误（验证失败）
    let error = crate::ResilienceError::config_error("business validation failed");
    let result = smart_handler.handle_error(&error, &context).await.unwrap();
    
    match result {
        ErrorHandlingResult::Skip => {
            // 业务错误应该跳过
        }
        _ => panic!("Expected skip for business error"),
    }
}

#[test]
fn test_error_handler_factory() {
    let retry_strategy = Arc::new(ExponentialBackoffStrategy::new(
        Duration::from_millis(100),
        Duration::from_secs(30),
        2.0
    ).with_max_attempts(3));
    
    let config = DeadLetterConfig::default();
    let dlq = Arc::new(InMemoryDeadLetterQueue::new(config));
    
    // 测试工厂方法
    let retry_handler = ErrorHandlerFactory::create_retry_handler(retry_strategy);
    assert_eq!(retry_handler.name(), "retry_handler");
    
    let dead_letter_handler = ErrorHandlerFactory::create_dead_letter_handler(dlq);
    assert_eq!(dead_letter_handler.name(), "dead_letter_handler");
    
    let skip_handler = ErrorHandlerFactory::create_skip_handler();
    assert_eq!(skip_handler.name(), "skip_handler");
    
    let composite_handler = ErrorHandlerFactory::create_composite_handler(vec![
        retry_handler,
        dead_letter_handler,
        skip_handler,
    ]);
    assert_eq!(composite_handler.name(), "composite_handler");
}

#[test]
fn test_backoff_strategy_calculate_delay() {
    // 测试固定延迟
    let fixed = BackoffStrategy::Fixed { delay_ms: 1000 };
    assert_eq!(fixed.calculate_delay(0), Duration::from_millis(1000));
    assert_eq!(fixed.calculate_delay(5), Duration::from_millis(1000));
    
    // 测试线性增长
    let linear = BackoffStrategy::Linear { 
        initial_delay_ms: 100, 
        increment_ms: 50 
    };
    assert_eq!(linear.calculate_delay(0), Duration::from_millis(100));
    assert_eq!(linear.calculate_delay(2), Duration::from_millis(200));
    assert_eq!(linear.calculate_delay(5), Duration::from_millis(350));
    
    // 测试指数退避
    let exponential = BackoffStrategy::Exponential { 
        initial_delay_ms: 100, 
        max_delay_ms: 5000, 
        multiplier: 2.0 
    };
    assert_eq!(exponential.calculate_delay(0), Duration::from_millis(100));
    assert_eq!(exponential.calculate_delay(1), Duration::from_millis(200));
    assert_eq!(exponential.calculate_delay(3), Duration::from_millis(800));
    
    // 测试最大延迟限制
    let capped_delay = exponential.calculate_delay(10);
    assert!(capped_delay <= Duration::from_millis(5000));
}

#[test]
fn test_error_handling_strategies() {
    // 测试重试策略
    let retry_strategy = ErrorHandlingStrategy::Retry {
        max_attempts: 3,
        backoff: BackoffStrategy::Exponential {
            initial_delay_ms: 100,
            max_delay_ms: 5000,
            multiplier: 2.0,
        },
    };
    
    match retry_strategy {
        ErrorHandlingStrategy::Retry { max_attempts, .. } => {
            assert_eq!(max_attempts, 3);
        }
        _ => panic!("Expected retry strategy"),
    }
    
    // 测试死信队列策略
    let dlq_strategy = ErrorHandlingStrategy::DeadLetter {
        dlq_topic: "test.dead.letter".to_string(),
    };
    
    match dlq_strategy {
        ErrorHandlingStrategy::DeadLetter { dlq_topic } => {
            assert_eq!(dlq_topic, "test.dead.letter");
        }
        _ => panic!("Expected dead letter strategy"),
    }
    
    // 测试组合策略
    let composite_strategy = ErrorHandlingStrategy::Composite {
        strategies: vec![
            ErrorHandlingStrategy::Retry {
                max_attempts: 2,
                backoff: BackoffStrategy::Fixed { delay_ms: 1000 },
            },
            ErrorHandlingStrategy::DeadLetter {
                dlq_topic: "fallback.dead.letter".to_string(),
            },
        ],
    };
    
    match composite_strategy {
        ErrorHandlingStrategy::Composite { strategies } => {
            assert_eq!(strategies.len(), 2);
        }
        _ => panic!("Expected composite strategy"),
    }
}

#[test]
fn test_error_context_creation() {
    let context = ErrorContext {
        component: "test-service".to_string(),
        retry_count: 2,
        message_id: Some("msg-456".to_string()),
        topic: Some("user.events".to_string()),
        attributes: {
            let mut attrs = std::collections::HashMap::new();
            attrs.insert("trace_id".to_string(), "trace-123".to_string());
            attrs.insert("span_id".to_string(), "span-456".to_string());
            attrs
        },
    };
    
    assert_eq!(context.component, "test-service");
    assert_eq!(context.retry_count, 2);
    assert_eq!(context.message_id, Some("msg-456".to_string()));
    assert_eq!(context.topic, Some("user.events".to_string()));
    assert_eq!(context.attributes.len(), 2);
    assert!(context.attributes.contains_key("trace_id"));
}

#[test]
fn test_error_handling_metrics_default() {
    let metrics = ErrorHandlingMetrics::default();
    
    assert_eq!(metrics.total_errors, 0);
    assert_eq!(metrics.retry_success_count, 0);
    assert_eq!(metrics.retry_failure_count, 0);
    assert_eq!(metrics.dead_letter_count, 0);
    assert_eq!(metrics.skip_count, 0);
    assert!(metrics.error_classification_stats.is_empty());
    assert!(metrics.last_updated <= chrono::Utc::now());
}